package com.yutons.encrypt.cryptor;

import cn.hutool.core.util.ReflectUtil;
import com.yutons.encrypt.config.MpEncryptProperties;
import com.yutons.encrypt.utils.SM4Util;

import java.lang.reflect.Field;
import java.util.Objects;

/**
 * @Title 加解密及脱敏接口自定义实现类
 * @Author yutons
 * @Date 2024-07-10 9:18
 * @Desc
 */
public class Sm4MpEncrypt implements IMpEncrypt {

	private final MpEncryptProperties properties;

	public Sm4MpEncrypt(MpEncryptProperties properties) {
		this.properties = properties;
	}

	/**
	 * 加密接口
	 *
	 * @param paramsObject mapper中paramsType的实例
	 * @param <T>          入参类型
	 * @return 返回加密
	 * @throws IllegalAccessException 字段不可访问异常
	 */
	@Override
	public <T> T encrypt(T paramsObject) throws IllegalAccessException {
		Class<?> paramsObjectClass = paramsObject.getClass();
		String clazzName = paramsObjectClass.getName();
		Field[] declaredFields = ReflectUtil.getFields(paramsObjectClass);
		//取出所有被FieldSensitive注解的字段
		for (Field field : declaredFields) {
			String propertyName = field.getName();
			MpEncryptProperties.SecretKey secretKey = properties.getSecretKey(clazzName, propertyName);

			// 校验注解
			if (!Objects.isNull(secretKey)) {
				field.setAccessible(true);
				Object object = field.get(paramsObject);

				// 目前只实现了String类的加密
				if (object instanceof String) {
					String value = (String) object;

					// 加密赋值
					String newValue = SM4Util.encode(value, secretKey);
					field.set(paramsObject, newValue);
				}
			}
		}
		return null;
	}

	/**
	 * 解密接口
	 *
	 * @param result resultType的实例
	 * @param <T>    入参类型
	 * @return 返回解密
	 * @throws IllegalAccessException 字段不可访问异常
	 */
	@Override
	public <T> T decrypt(T result) throws IllegalAccessException {
		//取出resultType的类
		Class<?> resultClass = result.getClass();
		String clazzName = resultClass.getName();
		Field[] declaredFields = ReflectUtil.getFields(resultClass);
		for (Field field : declaredFields) {
			String propertyName = field.getName();
			MpEncryptProperties.SecretKey secretKey = properties.getSecretKey(clazzName, propertyName);
			// 校验注解
			if (!Objects.isNull(secretKey)) {
				// 加解密属性
				field.setAccessible(true);
				Object object = field.get(result);
				// 目前只实现了String类的解密
				if (object instanceof String) {
					String value = (String) object;

					// 获取秘钥
					value = SM4Util.decode(value, secretKey);
					field.set(result, value);
				}
			}
		}
		return result;
	}
}
